#ifndef SJRPASSWORD_CONTEXT_BASIC1_HPP
#define SJRPASSWORD_CONTEXT_BASIC1_HPP

SJR_NAMESPACE_BEGIN

// storage init
class EpubContextBasic1 : public EpubContextBasic0 {
public:
  explicit EpubContextBasic1(std::string const &path)
      : EpubContextBasic0(), mOptions(), mDb(), mResult() {
    mOptions.create_if_missing = true;
    leveldb::DB::Open(mOptions, path, &mDb);
  }

  ~EpubContextBasic1() override {
    delete (mDb);
  }

  std::vector<unsigned char> &get(int num) {
    mResult.clear();

    auto &&key = leveldb::Slice(std::to_string(num));
    auto &&val = std::string();
    auto &&ret = (*mDb).Get(leveldb::ReadOptions(), key, &val);
    if (ret.ok()) {
      mResult.resize(val.size());
      memcpy(&mResult[0], &val[0], val.size());
    }
    return mResult;
  }

  template<class T>
  void put(int num, T const *data, int dataLen) {
    auto &&key = leveldb::Slice(std::to_string(num));
    auto &&val = leveldb::Slice(reinterpret_cast<char *>(const_cast<T *>(data)), dataLen);
    auto &&ret = (*mDb).Put(leveldb::WriteOptions(), key, val);
    if (!ret.ok())
      EpubLog::erro("EpubContextBasic1 put %s", ret.ToString().c_str());
  }

  template<class T>
  bool compare(int key1, T const *in, int inLen) {
    auto &&v = std::string();
    auto &&k = leveldb::Slice(std::to_string(key1));

    auto &&fun = leveldb::BytewiseComparator();
    auto &&ret = (*mDb).Get(leveldb::ReadOptions(), k, &v);
    if (!ret.ok())
      return false;

    auto &&inv = leveldb::Slice(reinterpret_cast<char *>(const_cast<T *>(in)), inLen);
    return ((*fun).Compare(v, inv) == 0);
  }

private:
  leveldb::Options mOptions;
  leveldb::DB *mDb;

  std::vector<unsigned char> mResult;
};

SJR_NAMESPACE_END

#endif//SJRPASSWORD_CONTEXT_BASIC1_HPP
